<template>
  <div
    class="bulk-node-container"
    :style="{
      color: themeStyle[theme].textColor1
    }"
  >
    <div
      class="title"
      :style="{
        borderBottom: `1px solid ${themeStyle[theme].borderColor1}`
      }"
    >
      <span style="color: #0087dc">{{ '批量节点' }}</span>
    </div>

    <!-- 对齐和等距 -->
    <div class="alignment">
      <template v-for="(item, index) in alignmentButton" :key="index">
        <div class="alignment-item" :title="item.title" @click="item.action">
          <svg-icon :name="item.icon"></svg-icon>
        </div>
      </template>
      <template v-for="(item, index) in equidistance" :key="index">
        <div
          v-if="selectCellList.length > 2"
          class="alignment-item"
          :title="item.title"
          @click="item.action"
        >
          <svg-icon :name="item.icon"></svg-icon>
        </div>
      </template>
    </div>

    <!-- 基准看齐 -->
    <div class="quick-connection">
      <span>基准看齐：</span>
      <template v-for="(item, index) in referenceAlignment" :key="index">
        <div class="quick-connection-item" :title="item.title" @click="item.action">
          <svg-icon :name="item.icon"></svg-icon>
        </div>
      </template>
    </div>

    <!-- 快速连线 -->
    <div class="quick-connection">
      <span>快速连线：</span>
      <template v-for="(item, index) in quickLink" :key="index">
        <div class="quick-connection-item" :title="item.title" @click="item.action">
          <svg-icon :name="item.icon"></svg-icon>
        </div>
      </template>
    </div>

    <div class="cell-list">
      <div
        class="cell-list-title"
        :style="{
          backgroundColor: themeStyle[theme].backgroundColor3
        }"
      >
        <span style="margin-left: 5px">节点列表</span>
        <CopyOutlined style="cursor: pointer; color: #999" @click="copyNodes" />
      </div>

      <div class="cell-list-content" :style="{ color: themeStyle[theme].textColor1 + 'aa' }">
        <template v-for="(item, index) in selectCellList" :key="index">
          <div class="cell-list-item">
            <span>{{ item.name }}</span>
            <span class="item-id">{{ item.id }}</span>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { useStyleStore } from '@renderer/store/globalStyle/style'
import { storeToRefs } from 'pinia'
import { onMounted, ref } from 'vue'
import { CopyOutlined } from '@ant-design/icons-vue'
import { useMessageStore } from '../../../store/message/message'
import { generateUUID } from '@renderer/utils/utils'

const globalStyleStore = useStyleStore()
const { theme, themeStyle } = storeToRefs(globalStyleStore)

//对齐
const alignmentButton = [
  {
    icon: 'canvasLeftAli',
    title: '左对齐',
    action: () => {
      handleAlign('left')
    }
  },
  {
    icon: 'canvasRightAli',
    title: '右对齐',
    action: () => {
      handleAlign('right')
    }
  },
  {
    icon: 'canvasTopAli',
    title: '上对齐',
    action: () => {
      handleAlign('top')
    }
  },
  {
    icon: 'canvasBottomAli',
    title: '下对齐',
    action: () => {
      handleAlign('bottom')
    }
  },
  {
    icon: 'canvasHorCenter',
    title: '水平居中',
    action: () => {
      handleAlign('v-center')
    }
  },
  {
    icon: 'canvasVerCenter',
    title: '垂直居中',
    action: () => {
      handleAlign('h-center')
    }
  }
]
//等距
const equidistance = [
  {
    icon: 'canvasHorDispersion',
    title: '水平等距',
    action: () => {
      handleAlign('h-distribute')
    }
  },
  {
    icon: 'canvasVerDispersion',
    title: '垂直等距',
    action: () => {
      handleAlign('v-distribute')
    }
  }
]
//基准看齐
const referenceAlignment = [
  {
    icon: 'directionRight',
    title: '向右',
    action: () => {
      handleReferenceAlign('left')
    }
  },
  {
    icon: 'directionLeft',
    title: '向左',
    action: () => {
      handleReferenceAlign('right')
    }
  },
  {
    icon: 'directionTop',
    title: '向上',
    action: () => {
      handleReferenceAlign('bottom')
    }
  },
  {
    icon: 'directionBottom',
    title: '向下连',
    action: () => {
      handleReferenceAlign('top')
    }
  }
]

//快速连线
const quickLink = [
  {
    icon: 'directionRight',
    title: '向右连线',
    action: () => {
      handleQuickConnect('left')
    }
  },
  {
    icon: 'directionLeft',
    title: '向左连线',
    action: () => {
      handleQuickConnect('right')
    }
  },
  {
    icon: 'directionTop',
    title: '向上连线',
    action: () => {
      handleQuickConnect('bottom')
    }
  },
  {
    icon: 'directionBottom',
    title: '向下连线',
    action: () => {
      handleQuickConnect('top')
    }
  }
]

type Node = { name: string; id: string; x: number; y: number; width: number; height: number }
const selectCellList = ref<Node[]>([])

onMounted(() => {
  initData()
  window.electron.ipcRenderer.on('canvasData', (e, mainData): void => {
    const { methodName, result } = mainData
    if (methodName === 'selectNodesOrEdges') {
      initData()
    }
  })
})

const initData = () => {
  //获取选择的节点列表
  const res = window.api.handleCanvasData('getSelectedNodesOrEdges', 'property', false, [])
  if (res && res.length > 0) {
    let temp = [] as Node[]
    res.forEach((item) => {
      const nodes = window.api.handleCanvasData('getNodes', 'property', false, ['id', item])
      if (nodes && nodes.length > 0) {
        const node = nodes[0]
        temp.push({
          name: node.name,
          id: node.id,
          x: node.x,
          y: node.y,
          width: node.width,
          height: node.height
        })
      }
    })
    selectCellList.value = temp
  }
}

type AlignType =
  | 'left'
  | 'right'
  | 'top'
  | 'bottom'
  | 'h-center'
  | 'v-center'
  | 'h-distribute'
  | 'v-distribute'

/**
 * 对节点进行对齐或分布排列
 * @param nodes 原始节点数组（至少 2 个）
 * @param type 对齐或分布类型
 * @returns 更新后节点数组（深拷贝）
 */
function alignNodes(nodes: Node[], type: AlignType): Node[] {
  if (nodes.length < 2) return nodes

  const sorted = [...nodes].sort((a, b) => (type.startsWith('v') ? a.y - b.y : a.x - b.x))

  const minX = Math.min(...nodes.map((n) => n.x))
  const maxX = Math.max(...nodes.map((n) => n.x + n.width))
  const minY = Math.min(...nodes.map((n) => n.y))
  const maxY = Math.max(...nodes.map((n) => n.y + n.height))

  const result = nodes.map((n) => ({ ...n })) // 深拷贝

  switch (type) {
    case 'left':
      result.forEach((n) => (n.x = minX))
      break
    case 'right':
      result.forEach((n) => (n.x = maxX - n.width))
      break
    case 'top':
      result.forEach((n) => (n.y = minY))
      break
    case 'bottom':
      result.forEach((n) => (n.y = maxY - n.height))
      break
    case 'h-center':
      const hCenter = (minX + maxX) / 2
      result.forEach((n) => (n.x = hCenter - n.width / 2))
      break
    case 'v-center':
      const vCenter = (minY + maxY) / 2
      result.forEach((n) => (n.y = vCenter - n.height / 2))
      break
    case 'h-distribute': {
      const totalWidth = sorted.reduce((sum, n) => sum + n.width, 0)
      const space = (maxX - minX - totalWidth) / (sorted.length - 1)
      let x = minX
      for (const n of sorted) {
        const r = result.find((item) => item.id === n.id)!
        r.x = x
        x += n.width + space
      }
      break
    }
    case 'v-distribute': {
      const totalHeight = sorted.reduce((sum, n) => sum + n.height, 0)
      const space = (maxY - minY - totalHeight) / (sorted.length - 1)
      let y = minY
      for (const n of sorted) {
        const r = result.find((item) => item.id === n.id)!
        r.y = y
        y += n.height + space
      }
      break
    }
  }

  return result
}

const handleAlign = (type: AlignType) => {
  const result = alignNodes(selectCellList.value, type)
  selectCellList.value = result
  const updateNodes = [] as any[]
  selectCellList.value.forEach((item) => {
    const nodes = window.api.handleCanvasData('getNodes', 'property', false, ['id', item.id])
    if (nodes && nodes.length > 0) {
      const node = nodes[0]
      node.x = item.x
      node.y = item.y
      updateNodes.push(node)
    }
  })
  if (updateNodes.length > 0) {
    window.api.handleCanvasData('updateNodes', 'property', true, [updateNodes])
  }
}

type Direction = 'left' | 'right' | 'top' | 'bottom'

//基准看齐
const handleReferenceAlign = (type: Direction) => {
  if (selectCellList.value.length === 0) return []
  // 创建一个副本防止原始数组被修改
  const sorted = [...selectCellList.value]

  switch (type) {
    case 'left':
      // 最左：按 x 升序排列
      sorted.sort((a, b) => a.x - b.x)
      for (let i = 1; i < sorted.length; i++) {
        sorted[i].x = sorted[i - 1].x + sorted[i - 1].width
      }
      break

    case 'right':
      // 最右：按 x 降序排列
      sorted.sort((a, b) => b.x - a.x)
      for (let i = 1; i < sorted.length; i++) {
        sorted[i].x = sorted[i - 1].x - sorted[i].width
      }
      break

    case 'top':
      // 最上：按 y 升序排列
      sorted.sort((a, b) => a.y - b.y)
      for (let i = 1; i < sorted.length; i++) {
        sorted[i].y = sorted[i - 1].y + sorted[i - 1].height
      }
      break

    case 'bottom':
      // 最下：按 y 降序排列
      sorted.sort((a, b) => b.y - a.y)
      for (let i = 1; i < sorted.length; i++) {
        sorted[i].y = sorted[i - 1].y + sorted[i].height
      }
      break
  }

  selectCellList.value = sorted

  //同步到主进程中
  const nodes = [] as any[]
  selectCellList.value.forEach((item) => {
    const nodeData = window.api.handleCanvasData('getNodes', 'property', false, ['id', item.id])
    if (nodeData) {
      const node = nodeData[0]
      node.x = item.x
      node.y = item.y
      nodes.push(node)
    }
  })

  if (nodes.length > 0) {
    window.api.handleCanvasData('updateNodes', 'property', true, [nodes])
  }
}

//快速连线
const handleQuickConnect = (type: Direction) => {
  if (selectCellList.value.length === 0) return []
  // 创建一个副本防止原始数组被修改
  const sorted = [...selectCellList.value]

  switch (type) {
    case 'left':
      // 最左：按 x 升序排列
      sorted.sort((a, b) => a.x - b.x)
      break
    case 'right':
      // 最右：按 x 降序排列
      sorted.sort((a, b) => b.x - a.x)
      break
    case 'top':
      // 最上：按 y 升序排列
      sorted.sort((a, b) => a.y - b.y)
      break
    case 'bottom':
      // 最下：按 y 降序排列
      sorted.sort((a, b) => b.y - a.y)
      break
  }

  //从主进程中获取到被选择的节点数据
  const selectNodes = [] as any[]
  //最后需要添加的边
  const addEdges = [] as any[]

  //获取所有的节点
  sorted.forEach((item) => {
    const nodeData = window.api.handleCanvasData('getNodes', 'property', false, ['id', item.id])
    if (nodeData) {
      selectNodes.push(nodeData[0])
    }
  })

  //获取所有的边
  const canvas = window.api.handleCanvasData('getCanvas', 'property', false, [])
  const edges = canvas.edges

  let prePort = ''
  let nextPort = ''
  switch (type) {
    case 'left':
      prePort = 'portRight'
      nextPort = 'portLeft'
      break
    case 'right':
      prePort = 'portLeft'
      nextPort = 'portRight'
      break
    case 'top':
      prePort = 'portBottom'
      nextPort = 'portTop'
      break
    case 'bottom':
      prePort = 'portTop'
      nextPort = 'portBottom'
      break
  }

  for (let i = 1; i < selectNodes.length; i++) {
    const preNode = selectNodes[i - 1]
    const preNodePortGroup = preNode?.style[prePort] || null

    const nextNode = selectNodes[i]
    const nextNodePortGroup = nextNode?.style[nextPort] || null

    //判断这条线存不存在
    const sourceId = preNode.id
    const targetId = nextNode.id

    const edge = edges.find((item) => item.sourceId === sourceId && item.targetId === targetId)
    if (edge) {
      continue
    }

    if (
      preNodePortGroup &&
      ['output', 'twoway'].includes(preNodePortGroup.type) &&
      nextNodePortGroup &&
      ['input', 'twoway'].includes(nextNodePortGroup.type)
    ) {
      const edgeData = {
        id: generateUUID(),
        shape: 'ordinary-edge',
        name: '普通边',
        sourceId: sourceId,
        sourcePortId: preNodePortGroup.id,
        targetId: targetId,
        targetPortId: nextNodePortGroup.id,
        simData: {
          isTransport: false,
          transportId: ''
        }
      }
      addEdges.push(edgeData)
    } else {
      continue
    }
  }

  if (addEdges.length > 0) {
    window.api.handleCanvasData('addEdges', 'property', true, [addEdges])
  }
}

const copyNodes = () => {
  //复制selectCellList内容
  navigator.clipboard.writeText(JSON.stringify(selectCellList.value))
  useMessageStore().addPrompt({
    source: '属性',
    content: '批量节点复制成功'
  })
}
</script>

<style scoped lang="scss">
.bulk-node-container {
  width: 100%;
  height: 100%;
  font-size: $font-size-medium;

  .title {
    padding: 3px 5px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-weight: bold;
  }

  .alignment {
    display: flex;
    height: 30px;
    justify-content: space-around;
    .alignment-item {
      cursor: pointer;
    }
  }

  .quick-connection {
    display: flex;
    height: 30px;
    justify-content: left;
    align-items: center;
    padding-left: 5px;
    font-size: $font-size-small;
    .quick-connection-item {
      cursor: pointer;
      width: 30px;
    }
  }

  .cell-list {
    margin-top: 10px;
    .cell-list-title {
      padding: 0px 5px;
      height: 25px;
      font-size: $font-size-small;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .cell-list-content {
      font-size: $font-size-small;
      padding: 0px 5px;
      .cell-list-item {
        margin-top: 5px;
        display: flex;
        justify-content: space-between;
        align-items: center;

        .item-id {
          width: 70px;
          overflow: hidden;
          text-overflow: ellipsis;
          text-wrap: nowrap;
        }
      }
    }
  }
}
</style>
